home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / c / c-tools-.000 / c-tools- / c-tools-0.4 / obscure.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-13  |  9.1 KB  |  414 lines

  1. /* obscure.c -- how to make a C source unreadable but compilable.
  2.    Copyright (C) 1995 Sandro Sigala - <sansig@freenet.hut.fi> */
  3.  
  4. /* $Id: obscure.c,v 1.27 1995/08/11 15:27:22 sandro Exp $ */
  5.  
  6. /* This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include <assert.h>
  22. #include <ctype.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #include <getopt.h>
  28.  
  29. #include "lex.h"
  30. #include "hash.h"
  31. #include "misc.h"
  32. #include "version.h"
  33.  
  34. #include "obscure.h"
  35.  
  36. FILE *input_file;
  37. FILE *output_file;
  38.  
  39. /* identifier prefix */
  40. static char prefix[128] = "q";
  41.  
  42. /* do not change identifiers option */ 
  43. static int opt_not_change_identifiers = 0;
  44.  
  45. /* make unreadable option */
  46. static int opt_make_unreadable = 0;
  47.  
  48. /* silly words option */
  49. static int opt_silly = 0;
  50.  
  51. /* prefix changed */
  52. static int opt_prefix = 0;
  53.  
  54. static int opt_width = 78;
  55. static int opt_width_changed = 0;
  56.  
  57. /* hash table for reserved identifiers */
  58. static struct hash_table *res_table;
  59.  
  60. /* hash table for identifiers */
  61. static struct hash_table *id_table;
  62.  
  63. /* number used for generating the identifiers */
  64. static int idnum = 0;
  65.  
  66. static int sillynum = 0;
  67. static int sillyrenum = 0;
  68.  
  69. /* add the identifier to the hash table and return a unique one */
  70.  
  71. char *
  72. add_identifier (char *s)
  73. {
  74.     char buf[128], *str;
  75.  
  76.     if (hash_table_lookup (id_table, s) == HASH_OK)
  77.     return ((char *) hash_table_retrive_data (id_table, s));
  78.  
  79.     assert (hash_table_add (id_table, s) == HASH_OK);
  80.  
  81.     if (!opt_silly)
  82.     sprintf (buf, "%s%d", prefix, idnum++);
  83.     else
  84.     {
  85.     if (!silly_words[sillynum])
  86.     {
  87.         sillynum = 0;
  88.         sillyrenum++;
  89.     }
  90.  
  91.     if (!opt_prefix)
  92.         buf[0] = '\0';
  93.     else
  94.         strcpy (buf, prefix);
  95.  
  96.     if (sillyrenum)
  97.     {
  98.         strcat (buf, silly_words[sillyrenum]);
  99.         strcat (buf, "_");    
  100.     }
  101.  
  102.     strcat (buf, silly_words[sillynum++]);
  103.     }
  104.  
  105.     str = (char *) xmalloc (strlen (buf) + 1);
  106.     strcpy (str, buf);
  107.     assert (hash_table_set_data (id_table, s, str) == HASH_OK);
  108.  
  109.     return str;
  110. }
  111.  
  112. static int column = 0;
  113.  
  114. static void
  115. outch (char c)
  116. {
  117.     if (c == '\n')
  118.     column = 0;
  119.     else
  120.     if (++column > opt_width && opt_width_changed)
  121.     {
  122.         putc ('\n', output_file);
  123.         column = 1;
  124.     }
  125.     putc (c, output_file);
  126. }
  127.  
  128. static void
  129. outstr (char *s)
  130. {
  131.     if (((column += strlen (s)) > opt_width) && opt_width_changed)
  132.     {
  133.     if (column - strlen (s) != 0)
  134.         putc ('\n', output_file);
  135.     column = strlen (s);
  136.     }
  137.  
  138.     while (*s)
  139.     fputc (*s++, output_file);
  140. }
  141.  
  142. void
  143. parse (void)
  144. {
  145.     int tk, last_token = 0, last_char = 0;
  146.     while ((tk = gettoken ()) != EOF)
  147.     {
  148.     switch (tk)
  149.     {
  150.     case COMMENT:
  151.         break;
  152.  
  153.     case IDENTIFIER:
  154.     {
  155.         char *p;
  156.         if (opt_not_change_identifiers)
  157.         p = lex_token_buffer;
  158.         else
  159.         {
  160.         if (hash_table_lookup (res_table, lex_token_buffer) == HASH_OK)
  161.             p = lex_token_buffer;
  162.         else
  163.             p = add_identifier (lex_token_buffer);
  164.  
  165.         last_char = p[strlen (p) - 1];
  166.  
  167.         if (opt_make_unreadable &&
  168.             (last_token == IDENTIFIER || last_token == NUMBER ||
  169.              (last_token >= KW_AUTO && last_token <= KW_WHILE)))
  170.             outch (' ');
  171.         }
  172.         outstr (p);
  173.         break;
  174.     }
  175.  
  176.     case NUMBER:
  177.         if (opt_make_unreadable > 0 &&
  178.         (last_token == IDENTIFIER || last_token == NUMBER ||
  179.          (last_token >= KW_AUTO && last_token <= KW_WHILE)))
  180.         outch (' ');
  181.         outstr (lex_token_buffer);
  182.         break;
  183.  
  184.     case CHARACTER: case STRING:
  185.         outstr (lex_token_buffer);
  186.         break;
  187.  
  188.     case DIRECTIVE:
  189.         if (opt_make_unreadable && last_token != 0 &&
  190.         last_token != DIRECTIVE && last_token != COMMENT)
  191.         outch ('\n');
  192.         outstr (lex_token_buffer);
  193.         column = 0;
  194.         break;
  195.  
  196.     case KW_AUTO: case KW_BREAK: case KW_CASE: case KW_CHAR:
  197.     case KW_CONST: case KW_CONTINUE: case KW_DEFAULT: case KW_DO:
  198.     case KW_DOUBLE: case KW_ELSE: case KW_ENUM: case KW_EXTERN:
  199.     case KW_FLOAT: case KW_FOR: case KW_GOTO: case KW_IF:
  200.     case KW_INT: case KW_LONG: case KW_REGISTER: case KW_RETURN:
  201.     case KW_SHORT: case KW_SIGNED: case KW_SIZEOF: case KW_STATIC:
  202.     case KW_STRUCT: case KW_SWITCH: case KW_TYPEDEF: case KW_UNION:
  203.     case KW_UNSIGNED: case KW_VOID: case KW_VOLATILE: case KW_WHILE:
  204.         if (opt_make_unreadable > 0 &&
  205.         (last_token == IDENTIFIER || last_token == NUMBER ||
  206.          (last_token >= KW_AUTO && last_token <= KW_WHILE)))
  207.         outch (' ');
  208.         outstr (lex_token_buffer);
  209.         break;
  210.  
  211.     case TK_DECREMENT: outstr ("--"); break;
  212.     case TK_INCREMENT: outstr ("++"); break;
  213.     case TK_ADD_ASSIGN: outstr ("+="); break;
  214.     case TK_SUB_ASSIGN: outstr ("-="); break;
  215.     case TK_MUL_ASSIGN: outstr ("*="); break;
  216.     case TK_DIV_ASSIGN: outstr ("/="); break;
  217.     case TK_MOD_ASSIGN: outstr ("%="); break;
  218.     case TK_AND_ASSIGN: outstr ("&="); break;
  219.     case TK_OR_ASSIGN: outstr ("|="); break;
  220.     case TK_XOR_ASSIGN: outstr ("^="); break;
  221.     case TK_LEFT_ASSIGN: outstr ("<<="); break;
  222.     case TK_RIGHT_ASSIGN: outstr (">>="); break;
  223.     case TK_PTR_OP: outstr ("->"); break;
  224.     case TK_EQ_OP: outstr ("=="); break;
  225.     case TK_NE_OP: outstr ("!="); break;
  226.     case TK_AND_OP: outstr ("&&"); break;
  227.     case TK_OR_OP: outstr ("||"); break;
  228.     case TK_GE_OP: outstr (">="); break;
  229.     case TK_LE_OP: outstr ("<="); break;
  230.     case TK_LEFT_OP: outstr ("<<"); break;
  231.     case TK_RIGHT_OP: outstr (">>"); break;
  232.     case TK_ELLIPSIS: outstr ("..."); break;
  233.  
  234.     default:
  235.         outch (tk);
  236.     }
  237.     last_token = tk;
  238.     }
  239. }
  240.  
  241. void
  242. add_reserved_ids (void)
  243. {
  244.     int i = 0;
  245.     while (reserved_ids [i])
  246.     hash_table_add (res_table, reserved_ids[i++]);
  247. }
  248.  
  249. void
  250. add_file_to_ids (struct hash_table *table, char *fname)
  251. {
  252.     FILE *f;
  253.     char buf[255];
  254.  
  255.     if ((f = fopen (fname, "r")) == NULL)
  256.     {
  257.     fprintf (stderr, "cannot open %s\n", fname);
  258.     exit (1);
  259.     }
  260.  
  261.     while (fgets (buf, 255, f) != NULL)
  262.     {
  263.     if (strlen (buf) > 1)
  264.     {
  265.         buf[strlen (buf) - 1] = '\0';
  266.         hash_table_add (table, buf);
  267.     }
  268.     }
  269.  
  270.     fclose (f);
  271. }
  272.  
  273. void
  274. helppage (char *progname)
  275. {
  276.     fprintf (stderr, "\
  277. %s %s - c-tools %s - Copyright (C) 1995 Sandro Sigala.\n\
  278. usage: %s [-huis] [-w width] [-a file] [-n file] [-p prefix]\n\
  279.                [input [output]]\n\
  280.        -h        display this help and exit\n\
  281.        -u        make very unreadable output\n\
  282.        -i        do not change identifiers\n\
  283.        -s        use silly words instead of numbers for the identifiers\n\
  284.        -w width  set the width of the output\n\
  285.        -a file   add first the identifiers contained in this file\n\
  286.        -n file   do not change the identifiers contained in this file\n\
  287.        -p prefix use this prefix as the prefix of the identifiers\n\
  288. ",
  289.          progname, VERSION_OBSCURE, VERSION_CTOOLS, progname);
  290.     exit (0);
  291. }
  292.  
  293. int
  294. main (int argc, char **argv)
  295. {
  296.     int c;
  297.  
  298.     id_table = hash_table_build ();
  299.     res_table = hash_table_build ();
  300.  
  301.     lex_return_white_spaces = 1;
  302.     lex_return_directives = 1;
  303.  
  304.     while (1)
  305.     {
  306.     c = getopt (argc, argv, "a:n:p:w:suih");
  307.     if (c == EOF)
  308.         break;
  309.  
  310.     switch (c)
  311.     {
  312.     case 'a':
  313.         if (!opt_not_change_identifiers)
  314.         add_file_to_ids (id_table, optarg);
  315.         else
  316.         fprintf (stderr, "parameter -a ignored\n");
  317.         break;
  318.  
  319.     case 'n':
  320.         if (!opt_not_change_identifiers)
  321.         add_file_to_ids (res_table, optarg);
  322.         else
  323.         fprintf (stderr, "parameter -f ignored\n");
  324.         break;
  325.  
  326.     case 'p':
  327.         if (!opt_not_change_identifiers)
  328.         {
  329.         strcpy (prefix, optarg);
  330.         opt_prefix = 1;
  331.         }
  332.         else
  333.         fprintf (stderr, "parameter -p ignored\n");
  334.         break;
  335.  
  336.     case 'u':
  337.         opt_make_unreadable = 1;
  338.         opt_width_changed = 1;
  339.         lex_return_white_spaces = 0;
  340.         break;
  341.  
  342.     case 'w':
  343.         opt_width = atoi (optarg);
  344.         opt_width_changed = 1;
  345.         if (opt_width < 2)
  346.         opt_width = 2;
  347.         break;
  348.  
  349.     case 's':
  350.         if (!opt_not_change_identifiers)
  351.         opt_silly = 1;
  352.         else
  353.         fprintf (stderr, "parameter -w ignored\n");
  354.         break;
  355.  
  356.     case 'i':
  357.         opt_not_change_identifiers = 1;
  358.         break;
  359.  
  360.     case 'h':
  361.     case '?':
  362.         helppage (argv[0]);
  363.         break;
  364.     }
  365.     }
  366.  
  367.     input_file = stdin;
  368.     output_file = stdout;
  369.  
  370.     if (optind < argc)
  371.     {
  372.     if ((argc - optind) > 2)
  373.         helppage (argv[0]);
  374.  
  375.     if (strcmp (argv[optind], "-") != 0)
  376.         input_file = fopen (argv[optind], "r");
  377.  
  378.     if ((argc - optind) > 1)
  379.         if (strcmp (argv[optind + 1], "-") != 0)
  380.         output_file = fopen (argv[optind + 1], "w");
  381.     }
  382.  
  383.     if (input_file == NULL)
  384.     {
  385.     fprintf (stderr, "%s: cannot open input file\n", argv[0]);
  386.     exit (1);
  387.     }
  388.  
  389.     if (output_file == NULL)
  390.     {
  391.     fprintf (stderr, "%s: cannot open output file\n", argv[0]);
  392.     exit (1);
  393.     }
  394.  
  395.     if (!opt_not_change_identifiers)
  396.     add_reserved_ids ();
  397.  
  398.     init_lex ();
  399.  
  400.     parse ();
  401.  
  402.     if (opt_make_unreadable)
  403.     outch ('\n');
  404.  
  405.     done_lex ();
  406.  
  407.     hash_table_free (id_table);
  408.     hash_table_free (res_table);
  409.  
  410.     return 0;
  411. }
  412.  
  413. /* obscure.c ends here */
  414.